﻿using GammaJul.ReSharper.GammaXaml.Psi.Xaml;
using JetBrains.ReSharper.Feature.Services.CSharp.Generate;
using JetBrains.ReSharper.Feature.Services.Generate;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.Xaml.Impl.Resolve;

namespace GammaJul.ReSharper.GammaXaml.Services.CSharp.Generate {

	/// <summary>
	/// Provides dependency properties fields for properties generation in a C# context.
	/// </summary>
	[GeneratorElementProvider(GeneratorStandardKinds.Properties, typeof(CSharpLanguage))]
	[GeneratorElementProvider(GeneratorStandardKinds.ReadProperties, typeof(CSharpLanguage))]
	internal sealed class DpFieldGeneratorProvider : GeneratorProviderBase<CSharpGeneratorContext> {
		
		public override void Populate(CSharpGeneratorContext context) {
			ITypeElement typeElement = context.ClassDeclaration.DeclaredElement;
			if (typeElement == null)
				return;

			IXamlTypeCache xamlTypeCache = XamlTypeCache.GetCache(context.PsiModule);

			foreach (IField dpField in typeElement.GetDpFields(xamlTypeCache)) {
				
				// finds the DpInitInfo from the DP field or the DP key field
				DpInitInfo dpInitInfo = dpField.GetDpOrDpKeyInitInfo(xamlTypeCache);
				if (dpInitInfo.RegistrationMethod == DpRegistrationMethod.Unknown) {
					IField dpKeyField = dpField.GetContainingType().GetDpKeyField(dpField.GetExpectedDpName(xamlTypeCache), xamlTypeCache);
					if (dpKeyField != null)
						dpInitInfo = dpKeyField.GetDpOrDpKeyInitInfo(xamlTypeCache);
				}

				// we can only generate a property if we know the DP registered type
				if (dpInitInfo.RegistrationMethod == DpRegistrationMethod.Unknown || dpInitInfo.RegisteredType == null)
					continue;

				if (dpInitInfo.RegistrationMethod.IsAttached()) {
					if (dpField.GetDpAttachedGetters(xamlTypeCache).Length == 0)
						context.ProvidedElements.Add(new DpGeneratorField(dpField, dpInitInfo.RegisteredType, true));
				}
				else if (dpField.GetDpClrProperty(xamlTypeCache) == null)
					context.ProvidedElements.Add(new DpGeneratorField(dpField, dpInitInfo.RegisteredType, false));
			}
		}

		public override double Priority {
			get { return -10.0; }
		}

	}
}